#include "sfu_call_agent.hpp"
#include "p2pms_log.hpp"

namespace p2pms
{

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
SFUCallAgent::SFUCallAgent(const std::string& user_id, IPcFactoryPtr factory, 
	ICallHandler* handler, rtc::Thread* thread, std::shared_ptr<IMsgDispatcher> dispatcher)
	: m_user_id(user_id)
	, m_call_handler(handler)
	, m_sfu_client(user_id, this, factory, thread, dispatcher)
{
	assert(!m_user_id.empty());
	assert(m_call_handler);
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
ErrCode SFUCallAgent::Init()
{
	return m_sfu_client.Init();
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
ErrCode SFUCallAgent::MakeCall(const std::string& callee_id)
{
	if (callee_id.empty()) {
		LOG_ERR("Room ID is empty");
		return ERR_INVALID_PARAM;
	}

	m_room_id = callee_id;

	auto result = m_sfu_client.JoinRoom(callee_id);
	if (result != ERR_OK) {
		LOG_ERR("Join room failed");
		return ERR_FAILED;
	}

	CallStateChanged(CallState::Calling);

	return ERR_OK;
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
ErrCode SFUCallAgent::IncomingCall(const CallMakeNotifyData& notify_data)
{
	// Room calls don't handle incoming calls - users join rooms directly
	LOG_WRN("Room call agent doesn't handle incoming calls");
	return ERR_FAILED;
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void SFUCallAgent::TerminateCall()
{
	CallStateChanged(CallState::Terminating);

	m_sfu_client.LeaveRoom();

	CallStateChanged(CallState::Terminated);
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
ErrCode SFUCallAgent::StartPublish(const MediaInfo& media)
{
	return m_sfu_client.StartPublish(media);
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
ErrCode SFUCallAgent::StopPublish(const MediaInfo& media)
{
	return m_sfu_client.StopPublish(media);
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
ErrCode SFUCallAgent::StartSubscribe(const std::string& user_id, const MediaInfo& media)
{
	return m_sfu_client.StartSubscribe(user_id, media);
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
ErrCode SFUCallAgent::StopSubscribe(const std::string& user_id, const MediaInfo& media)
{
	return m_sfu_client.StopSubscribe(user_id, media);
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
CallMode SFUCallAgent::GetCallMode()
{
	return CallMode::CALL_MODE_SFU;
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
std::string SFUCallAgent::GetCallerId()
{
	return m_user_id;
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
std::string SFUCallAgent::GetCalleeId()
{
	return m_room_id;
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
std::string SFUCallAgent::GetCallId()
{
	return m_room_id;
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
std::string SFUCallAgent::GetPeerUserId()
{
	return "";
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
std::string SFUCallAgent::GetUserId()
{
	return m_user_id;
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
CallState SFUCallAgent::GetCallState()
{
	return m_call_state;
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void SFUCallAgent::OnTimer()
{

}

////////////////////////////////////////////////////////////////////////////////////////////////////

void SFUCallAgent::CallStateChanged(CallState state)
{
	if (m_call_state != state) {
		m_call_state = state;
		if (m_call_handler) {
			m_call_handler->OnCallStateChanged(m_room_id, state);
		}
	}
	else {
		LOG_WRN("Call state unchanged: {}", state);
	}
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void SFUCallAgent::OnJoinRoomResult(bool result)
{
	result ? CallStateChanged(CallState::Connected) : CallStateChanged(CallState::Terminated);
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void SFUCallAgent::OnStartPublishResult(const MediaInfo& media, bool result)
{
	m_call_handler->OnStartPublishResult(media, result);
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void SFUCallAgent::OnStopPublishResult(const MediaInfo& media, bool result)
{
	m_call_handler->OnStopPublishResult(media, result);
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void SFUCallAgent::OnStartPublishNotify(const std::string& user_id, const MediaInfo& media)
{
	m_call_handler->OnStartPublish(user_id, media);
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void SFUCallAgent::OnStopPublishNotify(const std::string& user_id, const MediaInfo& media)
{
	m_call_handler->OnStopPublish(user_id, media);
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void SFUCallAgent::OnStartSubscribeResult(const std::string& user_id, const MediaInfo& media,
	bool result)
{
	m_call_handler->OnStartSubscribeResult(user_id, media, result);
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void SFUCallAgent::OnStopSubscribeResult(const std::string& user_id, const MediaInfo& media,
	bool result)
{
	m_call_handler->OnStopSubscribeResult(user_id, media, result);
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void SFUCallAgent::OnAddTrack(const std::string& user_id, const MediaInfo& media,
	webrtc::MediaStreamTrackInterface* track)
{
	m_call_handler->OnAddTrack(user_id, media, track);
}

//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void SFUCallAgent::OnRemoveTrack(const std::string& user_id, const MediaInfo& media,
	webrtc::MediaStreamTrackInterface* track)
{
	m_call_handler->OnRemoveTrack(user_id, media, track);
}

}